#include <assert.h>
#include "tcp_client.h"
#include "loop_controller.h"
static void internal_on_connect(uv_connect_t* conn, int status)
{
	tcp_client* clit = (tcp_client*)(conn->data);
	e_io_evt evt;
	evt = status == 0 ? e_tcp_conn_suc : e_tcp_conn_falied;
	clit->process_conn_status(evt);
}
static void  internal_on_reconnect(void *usrData)
{
	tcp_client* clit = (tcp_client*)(usrData);
	clit->process_reconn();
}

tcp_client::tcp_client()
{
	_uvtcp = (uv_tcp_t*)malloc(sizeof(uv_tcp_t));
	assert(_uvtcp);	
	_connect = (uv_connect_t*)malloc(sizeof(uv_connect_t));
	assert(_connect);
}


tcp_client::~tcp_client()
{	
	free_ptr();	
}

void tcp_client::connect(char* ip, size_t port)
{
	if (_bconnstatus){ return; }	
	struct sockaddr_in dest;
	uv_tcp_init(g_loop, _uvtcp);
	uv_ip4_addr(ip, port, &dest);
	_connect->data = this;
	uv_tcp_connect(_connect, _uvtcp, (const sockaddr*)&dest, internal_on_connect);
	_perrip = std::string(ip);
	_perrport = port;
	_stream = _connect->handle;
}
void tcp_client::process_on_close(uv_handle_t* handle)
{
	_bconnstatus = false;	
	if (_interanl_ms)
	{
		_uv_timer.start_timer(_interanl_ms, 0, internal_on_reconnect, this);
		return;
	}
	_close_cb(this);
}

void tcp_client::process_conn_status(e_io_evt evt)
{
	if (e_tcp_conn_suc == evt)
	{
		_bconnstatus = true;
		_connect->handle->data = this;
		uv_read_start(_connect->handle, internal_on_alloc_buf, internal_on_read);
	}
	else if (e_tcp_conn_falied == evt)
	{
		if (_interanl_ms > 0)
		{
			_uv_timer.start_timer(_interanl_ms, 0, internal_on_reconnect, this);
			return;
		}
	}
	_conn_cb(this, evt);
}

void tcp_client::free_ptr()
{
	if (_uvtcp){ free(_uvtcp); _uvtcp = nullptr; }
	if (_connect){ free(_connect); _connect = nullptr; }
}
void tcp_client::process_reconn()
{	
	connect((char*)_perrip.c_str(), _perrport);
}